using System;
using System.Windows.Input;
using Microsoft.Practices.CompositeUI.Commands;
using Microsoft.Practices.CompositeUI.Utility;

namespace SCSFContrib.CompositeUI.WPF.Commands
{
	/// <summary>
	/// Defines an <see cref="ICommand"/> that wraps a CAB <see cref="Command"/> for use within WPF.
	/// </summary>
	/// <remarks>
	/// <para>
	/// Instances of <c>WrappedCabCommand</c> wrap a CAB <see cref="Command"/> for consumption within a WPF environment. Note that
	/// no support is available for passing parameters to CAB command handlers. As such, any parameter specified for the WPF
	/// command will be ignored.
	/// </para>
	/// </remarks>
	public class WrappedCabCommand : ICommand
	{
		private readonly Command _command;

		/// <summary>
		/// Occurs when changes occur which affect whether or not the command should execute.
		/// </summary>
		public event EventHandler CanExecuteChanged;

		/// <summary>
		/// Constructs an instance of <c>CabCommand</c>.
		/// </summary>
		/// <param name="command">
		/// The CAB <see cref="Command"/> being wrapped by this <c>CabCommand</c>.
		/// </param>
		public WrappedCabCommand(Command command)
		{
			Guard.ArgumentNotNull(command, "command");
			_command = command;

			_command.Changed += delegate
			{
				OnCanExecuteChanged();
			};
		}

		/// <summary>
		/// Gets a value indicating whether the command can execute in its current state.
		/// </summary>
		/// <param name="parameter">
		/// An ignored parameter.
		/// </param>
		/// <returns>
		/// <see langword="true"/> if the command can execute, otherwise <see langword="false"/>.
		/// </returns>
		public bool CanExecute(object parameter)
		{
			return _command.Status == CommandStatus.Enabled;
		}

		/// <summary>
		/// Executes the command.
		/// </summary>
		/// <param name="parameter">
		/// An ignored parameter.
		/// </param>
		public void Execute(object parameter)
		{
			_command.Execute();
		}

		/// <summary>
		/// Raises the <see cref="CanExecuteChanged"/> event.
		/// </summary>
		protected virtual void OnCanExecuteChanged()
		{
			EventHandler handler = CanExecuteChanged;

			if (handler != null)
			{
				handler(this, EventArgs.Empty);
			}
		}
	}
}
